package com.delamer.facile;

import com.delamer.facile.db.*;
import com.delamer.facile.exe.*;
import com.delamer.facile.obj.*;
import com.delamer.facile.order.*;
import com.delamer.utils.MsgUtil;
import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;

import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public final class Main extends JavaPlugin implements CommandExecutor, TabCompleter {

    @Override
    public void onLoad() {
        doLoadConfig();
        doLoadDataBase();
    }

    @Override
    public void onEnable() {
        try {
            FileConfiguration config = getConfig();

            Objects.requireNonNull(getCommand("df")).setExecutor(createCEMain());
            Objects.requireNonNull(getCommand("df")).setTabCompleter(createTCMain());

            Objects.requireNonNull(getCommand("location")).setExecutor(createCELocation());
            Objects.requireNonNull(getCommand("location")).setTabCompleter(createTCLocation());

            Objects.requireNonNull(getCommand("permit")).setExecutor(createCEPermit());
            Objects.requireNonNull(getCommand("permit")).setTabCompleter(createTCPermit());

            Objects.requireNonNull(getCommand("warp")).setExecutor(createCEWarp());
            Objects.requireNonNull(getCommand("warp")).setTabCompleter(createTCWarp());

            Objects.requireNonNull(getCommand("home")).setExecutor(createCEHome());
            Objects.requireNonNull(getCommand("home")).setTabCompleter(createTCHome());

            Objects.requireNonNull(getCommand("tpa")).setExecutor(createCETpa());
            Objects.requireNonNull(getCommand("tpa")).setTabCompleter(createTCTpa());

            Objects.requireNonNull(getCommand("switch")).setExecutor(createCESwitch());
            Objects.requireNonNull(getCommand("switch")).setTabCompleter(createTCSwitch());

            for (String order : new OrderBase().getAll())
                Objects.requireNonNull(getCommand(order)).setExecutor(createCEBase());

            Bukkit.getPluginManager().registerEvents(new Monitor(config, this), this);
            runNotice(config);
            runClear(config);
            doConsoleSend(MsgUtil.msg("插件启动成功", true));
        } catch (Exception e) {
            e.printStackTrace();
            doConsoleSend(MsgUtil.err("插件启动失败", true));
            onDisable();
        }

    }

    private CommandExecutor createCEBase() {
        return new CommandExecutor() {
            @Override
            public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
                String command = new OrderBase().get(cmd.getName());
                if (command != null) {
                    try {
                        ExecutorBase.class.getMethod(command, CommandSender.class, String[].class).invoke(new ExecutorBase(), sender, args);
                    } catch (Exception e) {
                        e.printStackTrace();
                        String msg = "/" + label;
                        for (int i = 0; i < args.length; i++) msg = msg + " " + args[i];
                        doConsoleSend(MsgUtil.err("指令执行异常 -> " + sender.getName() + " : " + msg, true));
                        return false;
                    }
                }
                return true;
            }
        };
    }

    private CommandExecutor createCEMain() {
        return new CommandExecutor() {
            @Override
            public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
                //        String command = new Order().get(args.length > 0 ? args[0] : "help");
                String command = new Order().get(args.length > 0 ? args[0] : "menu");
                if (command != null) {
                    try {
                        Executor.class.getMethod(command, CommandSender.class, String[].class).invoke(new Executor(), sender, args);
                    } catch (Exception e) {
                        e.printStackTrace();
                        String msg = "/" + label;
                        for (int i = 0; i < args.length; i++) msg = msg + " " + args[i];
                        doConsoleSend(MsgUtil.err("指令执行异常 -> " + sender.getName() + " : " + msg, true));
                        return false;
                    }
                }
                return true;
            }
        };
    }

    private TabCompleter createTCMain() {
        return new TabCompleter() {
            @Override
            public List<String> onTabComplete(CommandSender sender, Command cmd, String label, String[] args) {
                Order orders = new Order();
                String players = "";
                for (Player player : Bukkit.getOnlinePlayers()) {
                    players = players + player.getName() + ",";
                }
                if (args.length > 1) return Arrays.asList(players.split(","));
                if (args.length == 0) return Arrays.asList(orders.getAll());
                return Arrays.stream(orders.getAll()).filter(s -> s.startsWith(args[0])).collect(Collectors.toList());
            }

        };
    }

    private CommandExecutor createCEPermit() {
        return new CommandExecutor() {
            @Override
            public boolean onCommand(CommandSender sender, Command cmd, String s, String[] args) {
                String command = new OrderPermit().get(args.length > 0 ? args[0] : "help");
                if (command != null) {
                    try {
                        ExecutorPermit.class.getMethod(command, CommandSender.class, String[].class).invoke(new ExecutorPermit(), sender, args);
                    } catch (Exception e) {
                        e.printStackTrace();
                        return false;
                    }
                }
                return true;
            }
        };
    }

    private TabCompleter createTCPermit() {
        return new TabCompleter() {
            @Override
            public List<String> onTabComplete(CommandSender sender, Command cmd, String label, String[] args) {
                OrderPermit orders = new OrderPermit();
                if (args.length == 0) return Arrays.asList(orders.getAll());
                if (args.length == 1)
                    return Arrays.stream(orders.getAll()).filter(s -> s.startsWith(args[0])).collect(Collectors.toList());
                if (args.length == 2) {
                    if (new ArrayList<String>() {{
                        add("info");
                        add("add");
                        add("del");
                    }}.contains(args[0])) {
                        try {
                            String players = "";
                            for (Player player : Bukkit.getOnlinePlayers())
                                players = players + player.getName() + ",";
                            return Arrays.asList(players.split(","));
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
                return new ArrayList<String>();
            }
        };
    }

    private CommandExecutor createCELocation() {
        return new CommandExecutor() {
            @Override
            public boolean onCommand(CommandSender sender, Command cmd, String s, String[] args) {
                String command = new OrderLocation().get(args.length > 0 ? args[0] : "help");
                if (command != null) {
                    try {
                        ExecutorLocation.class.getMethod(command, CommandSender.class, String[].class).invoke(new ExecutorLocation(), sender, args);
                    } catch (Exception e) {
                        e.printStackTrace();
                        return false;
                    }
                }
                return true;
            }
        };
    }

    private TabCompleter createTCLocation() {
        return new TabCompleter() {
            @Override
            public List<String> onTabComplete(CommandSender sender, Command cmd, String label, String[] args) {
                OrderLocation orders = new OrderLocation();
                if (args.length == 0) return Arrays.asList(orders.getAll());
                if (args.length == 1)
                    return Arrays.stream(orders.getAll()).filter(s -> s.startsWith(args[0])).collect(Collectors.toList());
                if (args.length == 2) {
                    if (new ArrayList<String>() {{
                        add("info");
                        add("send");
                    }}.contains(args[0])) {
                        try {
                            String players = "";
                            for (Player player : Bukkit.getOnlinePlayers())
                                players = players + player.getName() + ",";
                            return Arrays.asList(players.split(","));
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
                return new ArrayList<String>();
            }
        };
    }

    private CommandExecutor createCEWarp() {
        return new CommandExecutor() {
            @Override
            public boolean onCommand(CommandSender sender, Command cmd, String s, String[] args) {
                String command = new OrderWarp().get(args.length > 0 ? args[0] : "menu");
                if (command != null) {
                    try {
                        ExecutorWarp.class.getMethod(command, CommandSender.class, String[].class).invoke(new ExecutorWarp(), sender, args);
                    } catch (Exception e) {
                        e.printStackTrace();
                        return false;
                    }
                }
                return true;
            }
        };
    }

    private TabCompleter createTCWarp() {
        return new TabCompleter() {
            @Override
            public List<String> onTabComplete(CommandSender sender, Command cmd, String label, String[] args) {
                OrderWarp orders = new OrderWarp();
                if (args.length == 0) return Arrays.asList(orders.getAll());
                if (args.length == 1)
                    return Arrays.stream(orders.getAll()).filter(s -> s.startsWith(args[0])).collect(Collectors.toList());
                if (args.length > 1) {
                    if (new ArrayList<String>() {{
                        add("info");
                        add("del");
                        add("set");
                        add("tp");
                    }}.contains(args[0])) {
                        String warps = "";
                        try {
                            List<ObjectWarp> list = DBUtilWarp.getWarpList();
                            for (ObjectWarp objectWarp : list)
                                warps = warps + objectWarp.getWarpName() + ",";
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        return Arrays.asList(warps.split(","));
                    }
                }
                return new ArrayList<String>();
            }
        };
    }

    private CommandExecutor createCEHome() {
        return new CommandExecutor() {
            @Override
            public boolean onCommand(CommandSender sender, Command cmd, String s, String[] args) {
                String command = new OrderHome().get(args.length > 0 ? args[0] : "help");
                if (command != null) {
                    try {
                        ExecutorHome.class.getMethod(command, CommandSender.class, String[].class).invoke(new ExecutorHome(), sender, args);
                    } catch (Exception e) {
                        e.printStackTrace();
                        return false;
                    }
                }
                return true;
            }
        };
    }

    private TabCompleter createTCHome() {
        return new TabCompleter() {
            @Override
            public List<String> onTabComplete(CommandSender sender, Command cmd, String label, String[] args) {
                OrderHome orders = new OrderHome();
                if (args.length == 0) return Arrays.asList(orders.getAll());
                if (args.length == 1)
                    return Arrays.stream(orders.getAll()).filter(s -> s.startsWith(args[0])).collect(Collectors.toList());
                if (args.length > 1) {
                    if (new ArrayList<String>() {{
                        add("info");
                        add("del");
                        add("set");
                        add("tp");
                    }}.contains(args[0])) {
                        String warps = "";
                        try {
                            List<ObjectHome> list = DBUtilHome.getHomeList(sender.getName());
                            for (ObjectHome object : list)
                                warps = warps + object.getHomeName() + ",";
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        return Arrays.asList(warps.split(","));
                    }
                }
                return new ArrayList<String>();
            }
        };
    }

    private CommandExecutor createCETpa() {
        return new CommandExecutor() {
            @Override
            public boolean onCommand(CommandSender sender, Command cmd, String s, String[] args) {
                String command = new OrderTpa().get(args.length > 0 ? args[0] : "help");
                if (command != null) {
                    try {
                        ExecutorTpa.class.getMethod(command, CommandSender.class, String[].class).invoke(new ExecutorTpa(), sender, args);
                    } catch (Exception e) {
                        e.printStackTrace();
                        return false;
                    }
                }
                return true;
            }
        };
    }

    private TabCompleter createTCTpa() {
        return new TabCompleter() {
            @Override
            public List<String> onTabComplete(CommandSender sender, Command cmd, String label, String[] args) {
                OrderTpa orders = new OrderTpa();
                if (args.length == 0) return Arrays.asList(orders.getAll());
                if (args.length == 1)
                    return Arrays.stream(orders.getAll()).filter(s -> s.startsWith(args[0])).collect(Collectors.toList());
                if (args.length > 1) {
                    if (new ArrayList<String>() {{
                        add("apply");
                        add("here");
                        add("accept");
                        add("reject");
                    }}.contains(args[0])) {
                        try {
                            String players = "";
                            for (Player player : Bukkit.getOnlinePlayers())
                                players = players + player.getName() + ",";
                            return Arrays.asList(players.split(","));
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
                return new ArrayList<String>();
            }
        };
    }

    private CommandExecutor createCESwitch() {
        return new CommandExecutor() {
            @Override
            public boolean onCommand(CommandSender sender, Command cmd, String s, String[] args) {
                String command = new OrderSwitch().get(args.length > 0 ? args[0] : "help");
                if (command != null) {
                    try {
                        ExecutorSwitch.class.getMethod(command, CommandSender.class, String[].class).invoke(new ExecutorSwitch(), sender, args);
                    } catch (Exception e) {
                        e.printStackTrace();
                        return false;
                    }
                }
                return true;
            }
        };
    }

    private TabCompleter createTCSwitch() {
        return new TabCompleter() {
            @Override
            public List<String> onTabComplete(CommandSender sender, Command cmd, String label, String[] args) {
                OrderSwitch orders = new OrderSwitch();
                if (args.length == 0) return Arrays.asList(orders.getAll());
                if (args.length == 1)
                    return Arrays.stream(orders.getAll()).filter(s -> s.startsWith(args[0])).collect(Collectors.toList());
                if (args.length > 1) {
                    if (new ArrayList<String>() {{
                        add("color");
                        add("keep");
                    }}.contains(args[0])) {
                        try {
                            String players = "";
                            for (Player player : Bukkit.getOnlinePlayers())
                                players = players + player.getName() + ",";
                            return Arrays.asList(players.split(","));
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
                return new ArrayList<String>();
            }
        };
    }

    @Override
    public void onDisable() {
        doConsoleSend(MsgUtil.err("插件已停止运行", true));
    }


    private void doLoadConfig() {
        try {
            {
                File file = getDataFolder();
                if (!file.exists())
                    file.mkdir();
            }
            {
                File file = new File(getDataFolder(), "config.yml");
                if (!file.exists())
                    saveDefaultConfig();
            }
            {
                File file = new File(getDataFolder(), "menu-main.yml");
                if (!file.exists()) {
                    file.createNewFile();
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(getResource("menu-main.yml"), "UTF-8"));
                    BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
                    try {
                        String line = null;
                        while ((line = bufferedReader.readLine()) != null) {
                            bufferedWriter.write(line);
                            bufferedWriter.newLine();
                        }
                        bufferedWriter.flush();
                    } catch (Exception e) {
                        bufferedReader.close();
                        bufferedWriter.close();
                        throw e;
                    }
                    bufferedReader.close();
                    bufferedWriter.close();
                }
            }
            {
                File file = new File(getDataFolder(), "menu-warp.yml");
                if (!file.exists()) {
                    file.createNewFile();
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(getResource("menu-warp.yml"), "UTF-8"));
                    BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
                    try {
                        String line = null;
                        while ((line = bufferedReader.readLine()) != null) {
                            bufferedWriter.write(line);
                            bufferedWriter.newLine();
                        }
                        bufferedWriter.flush();
                    } catch (Exception e) {
                        bufferedReader.close();
                        bufferedWriter.close();
                        throw e;
                    }
                    bufferedReader.close();
                    bufferedWriter.close();
                }
            }
            {
                File file = new File(getDataFolder(), "menu-quest.yml");
                if (!file.exists()) {
                    file.createNewFile();
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(getResource("menu-quest.yml"), "UTF-8"));
                    BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
                    try {
                        String line = null;
                        while ((line = bufferedReader.readLine()) != null) {
                            bufferedWriter.write(line);
                            bufferedWriter.newLine();
                        }
                        bufferedWriter.flush();
                    } catch (Exception e) {
                        bufferedReader.close();
                        bufferedWriter.close();
                        throw e;
                    }
                    bufferedReader.close();
                    bufferedWriter.close();
                }
            }
            doConsoleSend(MsgUtil.msg("配置文件加载成功", true));
        } catch (Exception e) {
            e.printStackTrace();
            doConsoleSend(MsgUtil.err("配置文件加载失败", true));
        }
    }

    private void doLoadDataBase() {
        try {
            DBUtilSwitch.init();
            DBUtilPermit.init();
            DBUtilWarp.init();
            DBUtilHome.init();
            DBUtilTpa.init();
            DBUtilQuest.init();
            DBUtilBack.init();
        } catch (Exception e) {
            e.printStackTrace();
            doConsoleSend(MsgUtil.err("数据库连接失败", true));
        }
    }

    private void doConsoleSend(String str) {
        Bukkit.getConsoleSender().sendMessage(str);
    }

    private void runNotice(FileConfiguration config) {
        try {
            new BukkitRunnable() {
                private List<String> list = config.getStringList("notice.list");
                private Integer period = list.size();
                private Integer counter = 0;

                @Override
                public void run() {
                    if (config.getBoolean("notice.chat"))
                        Bukkit.broadcastMessage(list.get(counter));
                    if (config.getBoolean("notice.bar")) {
                        TextComponent message = new TextComponent(list.get(counter));
                        for (Player player : Bukkit.getOnlinePlayers())
                            player.spigot().sendMessage(ChatMessageType.ACTION_BAR, message);
                    }
                    counter = counter + 2 > period ? 0 : counter + 1;
                }
            }.runTaskTimer(this, 0, config.getInt("notice.time") * 20);
            Bukkit.getConsoleSender().sendMessage("定时公告启用成功");
        } catch (Exception e) {
            Bukkit.getConsoleSender().sendMessage("定时公告启用失败");
        }
    }

    private void runClear(FileConfiguration config) {
        try {
            JavaPlugin plugin = this;
            new BukkitRunnable() {
                private Integer period = config.getInt("clear.period");
                private Integer remainder = config.getInt("clear.remainder");
                private Integer countdown = config.getInt("clear.countdown");
                private String remainderContent = config.getString("clear.remainder-content");
                private String countdownContent = config.getString("clear.countdown-content");
                private String finishContent = config.getString("clear.finish-content");
                private Integer counter = 0;

                @Override
                public void run() {
                    if (counter >= period) {
                        new BukkitRunnable() {
                            private Integer count = 0;

                            @Override
                            public void run() {
                                if (config.getBoolean("clear.chat"))
                                    Bukkit.broadcastMessage(countdownContent.replace("<%Time%>", String.valueOf(countdown - count)));
                                if (config.getBoolean("clear.bar")) {
                                    TextComponent message = new TextComponent(countdownContent.replace("<%Time%>", String.valueOf(countdown - count)));
                                    for (Player player : Bukkit.getOnlinePlayers())
                                        player.spigot().sendMessage(ChatMessageType.ACTION_BAR, message);
                                }
                                if (count >= countdown) {
                                    Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "kill @e[type=item]");
                                    if (config.getBoolean("clear.chat"))
                                        Bukkit.broadcastMessage(finishContent);
                                    if (config.getBoolean("clear.bar")) {
                                        TextComponent message = new TextComponent(finishContent);
                                        for (Player player : Bukkit.getOnlinePlayers())
                                            player.spigot().sendMessage(ChatMessageType.ACTION_BAR, message);
                                    }
                                    this.cancel();
                                }
                                count++;
                            }
                        }.runTaskTimer(plugin, 0, 20);
                    } else if (counter % remainder == 0 || period - counter == 1) {
                        if (config.getBoolean("clear.chat"))
                            Bukkit.broadcastMessage(remainderContent.replace("<%Time%>", String.valueOf(period - counter)));
                        if (config.getBoolean("clear.bar")) {
                            TextComponent message = new TextComponent(remainderContent.replace("<%Time%>", String.valueOf(period - counter)));
                            for (Player player : Bukkit.getOnlinePlayers())
                                player.spigot().sendMessage(ChatMessageType.ACTION_BAR, message);
                        }
                    }
                    counter = counter >= period ? 0 : counter + 1;
                }
            }.runTaskTimer(plugin, 0, config.getInt("clear.unit") * 20);
            Bukkit.getConsoleSender().sendMessage("定时清理启用成功");
        } catch (Exception e) {
            Bukkit.getConsoleSender().sendMessage("定时清理启用失败");
        }
    }
}
